//
//  main.m
//  08 - IOS9新特性（;、泛型 __kindof）
//
//  Created by 韩旭 on 16/7/13.
//  Copyright © 2016年 基础. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
#pragma mark -
#if 0
        {
            Person *person = [[Person alloc] init];
            //        nonull修饰的属性，对应的getter 和 setter方法
            person.name = nil;
            person.name = @"张三";
            
            //         nullable 修饰的属性, 对应的getter 和 setter方法
            //        person setSex:<#(NSString * _Nullable)#>
            //        [person sex];
            //        person.sex = nil;
            //        null_resettable
            [person setFriends:nil];
            
            [person friends];

            
            
        }
#endif
        #pragma mark - 知识点2
#if 0
        {
//           2 泛型
//            带泛型的容器（规定了容器中所存储的类型）
//            代表的意思：声明一个可变数组，内部存放的都是NSString
            //            1. 好处数组中不能放其他的内容 会有警告
            //            2. 数组取出来的类型不在是id类型, 对应变成声明时的类型
//            3. 泛型会改变类的一些方法, 使与声明的类型相同
            NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"123", nil];
            NSLog(@"%ldld", array.firstObject.length);
            [array addObject:@"12"];
            [array addObject:@"person"];
            [array addObject:@"er~~~"];
//            [array addObject:@3];
            NSInteger indege = [array objectAtIndex:0].length;
//            带泛型的字典
            NSMutableDictionary<NSString *, NSString *> *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"于涵", @"name", nil];
            
        }
#endif
        
#pragma mark - 自定义泛型
#if 0
        {
            
            Person *person = [[Person alloc] init];
            //        nonull修饰的属性，对应的getter 和 setter方法
//            person.name = nil;
            person.name = @"张三";
//            自定义泛型

            Truck<Person *> *truckPer = [[Truck alloc] init];
            
            Truck<Student *> *truckStu = [[Truck alloc] init];

            Student *stu = [[Student alloc] init];
            stu.stuNumber = @"0001";
            [truckStu addObject:stu];
            [truckStu addObject:person];
            [truckStu addObject:person];
            [truckPer addObject:stu];
//            协变性和异变性

            Truck *truck = nil;
            Truck<NSArray *> *truck1 = nil;
            Truck<NSMutableArray *> *truck2 = nil;
//   大类型（任意类型） 可以给有泛型的赋值
//            也可以有泛型的指针
            truck = truck1;
            truck = truck2;
            truck1 = truck;
            truck2 = truck;
            
//            __covariant 协变性 子类在给弗雷赋值时, 自动强转
//        Truck<NSArray *> 与 truck<NSDictionary *>
            truck1 = truck2;
//            __contravariant 逆变性 父类给子类赋值, 自动强转（不知道应用到何处）
            truck2 = truck1;
        }
#endif
#pragma mark - kindof
#if 1
        {
//          3  kindof
//            加__kindof修饰后, 返回的类型及其子类型，都可以接收这个返回值
            Truck *truck = [[Truck alloc] init];
          NSArray *arr = [truck retainArray];
            NSMutableArray *arrMutable = [truck retainArray];
            NSLog(@"%@", arrMutable);
        }
#endif
    }
    return 0;
}
